package com.dataStructures.huffmantree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 赫夫曼树：树的带权路径长度(wpl)达到最小的树
 */
public class HuffmanTree {
	public static void main(String[] args) {
		int arr[] = {13, 7, 8, 3, 29, 6, 1};
		Node huffmanTree = createHuffmanTree(arr);
		huffmanTree.preOrder();
	}

	/**
	 * 创建一个赫夫曼树
	 *
	 * @param arr 数组
	 * @return 赫夫曼树的根节点
	 */
	public static Node createHuffmanTree(int[] arr) {
		// 1. 遍历数组，每个元素构建 Node，放入 List
		List<Node> nodeList = new ArrayList<>();
		for (final int i : arr) {
			nodeList.add(new Node(i));
		}
		// 最终 List 里只存放赫夫曼树的 root 节点（只有一个元素）
		while (nodeList.size() > 1) {
			// 1. sort list
			Collections.sort(nodeList);
			// 2. 取出根节点权值最小的两棵树
			Node leftNode = nodeList.get(0);
			Node rightNode = nodeList.get(1);
			// 3. 构建一棵新的二叉树
			Node parentNode = new Node(leftNode.value + rightNode.value);
			parentNode.left = leftNode;
			parentNode.right = rightNode;
			// 4. 从 ArrayList 删除处理过的二叉树
			nodeList.remove(leftNode);
			nodeList.remove(rightNode);
			// 5. 将 parent 加入到 nodes
			nodeList.add(parentNode);
		}
		return nodeList.get(0);
	}

	/**
	 * 前序遍历
	 *
	 * @param root 根节点
	 */
	public static void preOrder(Node root) {
		if (root != null) {
			root.preOrder();
		}
	}
}

class Node implements Comparable<Node> {
	int value;
	Node left;
	Node right;

	public Node(final int value) {
		this.value = value;
	}

	/**
	 * 前序遍历
	 */
	public void preOrder() {
		System.out.println(this);
		if (this.left != null) {
			this.left.preOrder();
		}
		if (this.right != null) {
			this.right.preOrder();
		}
	}

	public String toString() {
		final StringBuffer sb = new StringBuffer("Node{");
		sb.append("value=").append(value);
		sb.append('}');
		return sb.toString();
	}

	/**
	 * 表示从小到大排序
	 *
	 * @param o
	 * @return
	 */
	@Override
	public int compareTo(Node o) {
		return this.value - o.value;
	}
}
